﻿/* dk2Repository - Copyright (C) 2011 Daniel Kuczewski http://www.dk2.de/

 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */

using System;
using System.Data;

namespace dk2Database.Commands
{

    /// <summary>
    /// Query Command with generic return type
    /// Bypasses DataReader to derived class
    /// </summary>
    /// <typeparam name="T">return type</typeparam>
    public abstract class QueryEntityCommandBase<T> : CommandBase
    {
        protected QueryEntityCommandBase(string sql) : base(sql) { }

        protected QueryEntityCommandBase(string sql, CommandParameters parameters) : base(sql, parameters) { }

        protected QueryEntityCommandBase(string sql, params object[] parameters) : base(sql, parameters) { }

        public abstract T ProcessDataReader(IDataReader reader);

        public virtual void BeforeExecute() { }
        public virtual void AfterExecute(T result) { }

        public T Result { get; set; }

        public override void Execute()
        {
            BeforeExecute();

            try
            {
                using (var con = ConnectionFactory.CreateConnection())
                {
                    using (var dbcmd = con.CreateCommand())
                    {
                        try
                        {
                            SetDbCommand(dbcmd);
                        }
                        catch (Exception ex)
                        {
                            throw new CreateDbCommandException(this, ex.Message);
                        }


                        using (var reader = dbcmd.ExecuteReader())
                        {
                            Result = ProcessDataReader(reader);
                        }

                    }
                }

                AfterExecute(Result);

            }
            catch (ConnectionException)
            {
                throw;
            }
            catch (Exception ex)
            {
                var ex2 = new CommandException(Sql, ex.Message);
                OnError(ex2);
                throw ex2;
            }            
        }
    }

}